<?php

namespace App\Models;

use App\Http\Controllers\ScoreRuleController;
use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**活动申请model */
class ActivityApply extends BaseModel
{
    use HasFactory;

    const CREATED_AT = 'create_time';
    const UPDATED_AT = 'change_time';

    protected $table = 'activity_apply';




    /*关联用户*/
    public function conUser()
    {
        return $this->hasOne(UserInfo::class, 'id', 'user_id');
    }

    /*关联活动*/
    public function conActivity()
    {
        return $this->hasOne(Activity::class, 'id', 'act_id');
    }

    /*关联签到信息*/
    public function conSign()
    {
        return $this->hasMany(ActivitySign::class, 'apply_id', 'id');
    }

    /*关联操作人员信息*/
    public function conManage()
    {
        return $this->hasOne(Manage::class, 'id', 'manage_id');
    }

    /**
     * 获取我的报名信息
     */
    public function getApplyInfo($user_id, $act_id, $apply_id = null)
    {
        return $this->where('user_id', $user_id)
            ->where('act_id', $act_id)
            ->where(function ($query) use ($apply_id) {
                if ($apply_id) {
                    $query->where('id', $apply_id);
                }
            })
            ->orderByDesc('id')
            ->first();
    }

    /**
     * 获取用户列表（只查询审核通过的）
     * @param act_id int 活动id
     * @param page int 页码
     * @param limit int 分页大小
     * @param keywords string 搜索关键词
     * @param keywords_type string 关键词类型 username(名称) id_card(身份证) tel(电话) reader_id(读者证) qr_code(二维码)
     * @param is_sign 是否签到 0全部 1已签到 2未签到  默认等于2
     * @param start_time 报名开始时间
     * @param end_time 报名结束时间
     * @param status int 报名状态  0全部   1.已通过  3.已拒绝  4.审核中  数组形式
     */
    public function activityApplyUserList($act_id, $status, $keywords_type, $keywords, $start_time, $end_time, $is_sign, $limit)
    {
        if (empty($act_id)) {
            return [];
        }
        //查询当前活动，今日已签到的apply_id
        $apply_id_all = [];
        if ($is_sign == 1 || $is_sign == 2) {
            $apply_id_all = $this->getActApplyId($act_id);
        }
        // DB::enableQueryLog();
        $res = $this->from($this->getTable() . ' as p')
            ->select(
                'u.id as user_id',
                'u.account_id',
                'u.wechat_id',
                //  'u.activity_violate_num',
                'p.id',
                'p.status',
                'p.reason',
                'p.sign_num',
                'p.username',
                'p.id_card',
                'p.tel',
                'p.reader_id',
                'p.img',
                'p.is_violate',
                'p.violate_reason',
                'p.violate_time',
                'p.score',
                'p.unit',
                'p.age',
                'p.sex',
                'p.school',
                'p.grade',
                'p.class_grade',
                'p.wechat_number',
                'p.remark',
                'p.manage_id',
                'p.create_time',
                'p.change_time',
                'a.title',
                DB::raw("if(status = 4,1,0) as order_num")
            )
            ->join('activity as a', 'a.id', '=', 'p.act_id')
            ->join('user_info as u', 'u.id', '=', 'p.user_id')
            ->where(function ($query) use ($keywords_type, $keywords) {
                if ($keywords) {
                    if ($keywords_type == 'qr_code') {
                        $query->where('u.' . $keywords_type, 'like', '%' . $keywords . '%');
                    } elseif ($keywords_type) {
                        $query->where('p.' . $keywords_type, 'like', '%' . $keywords . '%');
                    } else {
                        $query->where('p.username', 'like', '%' . $keywords . '%')
                            ->orWhere('p.id_card', 'like', '%' . $keywords . '%')
                            ->orWhere('p.tel', 'like', '%' . $keywords . '%')
                            ->orWhere('p.reader_id', 'like', '%' . $keywords . '%')
                            ->orWhere('u.qr_code', 'like', '%' . $keywords . '%');
                    }
                }
            })->where(function ($query) use ($apply_id_all, $status, $start_time, $end_time, $is_sign) {
                if ($status) {
                    if (!is_array($status)) {
                        $status = explode(',', $status);
                    }
                    $query->whereIn('p.status', $status);
                }
                if ($start_time && $end_time) {
                    $query->whereBetween('p.create_time', [$start_time, $end_time]);
                }
                if ($is_sign == 1) {
                    //查询全部已签到的apply_id
                    $query->whereIn('p.id',  $apply_id_all);
                } elseif ($is_sign == 2) {
                    $query->whereNotIn('p.id', $apply_id_all);
                }
            })
            ->with(['conSign' => function ($query) {
                $query->select('act_id', 'apply_id', 'user_id', 'date', 'create_time');
            }, 'conManage'])
            ->where(function ($query) use ($act_id) {
                if ($act_id) {
                    $act_id = !is_array($act_id) ? explode(',', $act_id) : $act_id;
                    $query->whereIn('p.act_id', $act_id);
                }
            })
            ->orderByDesc('act_id')
            ->orderByDesc('order_num')
            ->orderByDesc('p.create_time')
            ->paginate($limit)
            ->toArray();
        foreach ($res['data'] as $key => $val) {
            if ($val['con_sign']) {
                $last = end($val['con_sign']);
                $res['data'][$key]['last_sign_date'] = $last['create_time'];
                $res['data'][$key]['is_sign'] = date("Y-m-d", strtotime($last['create_time'])) == date("Y-m-d", time()) ? 1 : 2;
            } else {
                $res['data'][$key]['last_sign_date'] = null;
                $res['data'][$key]['con_sign'] = null;
                $res['data'][$key]['is_sign'] = 2;
            }
            if ($val['con_manage']) {
                $res['data'][$key]['manage_name'] = $val['con_manage'][Manage::$manage_name];
            } else {
                $res['data'][$key]['manage_name'] = '';
            }
            unset($res['data'][$key]['con_manage']);

            if ($val['wechat_id']) {
                $wechat_info = UserWechatInfo::where('id', $val['wechat_id'])->first();
                if ($wechat_info) {
                    $res['data'][$key]['nickname'] = $wechat_info['nickname'];
                    $res['data'][$key]['head_img'] = $wechat_info['head_img'];
                }
            } else {
                $res['data'][$key]['nickname'] = null;
                $res['data'][$key]['head_img'] = null;
            }

            //重置用户填写信息
            if ($val['account_id']) {
                $user_account_info = UserLibraryInfo::where('id', $val['account_id'])->first();
                if ($user_account_info) {
                    $res['data'][$key]['id_card'] = $val['id_card'] ? $val['id_card'] : $user_account_info['id_card'];
                    $res['data'][$key]['sex'] = $val['sex'] ? $val['sex'] : $user_account_info['sex'];
                    $res['data'][$key]['tel'] = $val['tel'] ? $val['tel'] : $user_account_info['tel'];
                    $res['data'][$key]['age'] = $val['age'] ? $val['age'] : ($user_account_info['id_card'] ?  get_user_age_by_id_card($user_account_info['id_card']) : '');
                    $res['data'][$key]['reader_id'] = $val['reader_id'] ? $val['reader_id'] : $user_account_info['account'];
                    $res['data'][$key]['username'] = $val['username'] ? $val['username'] : $user_account_info['username'];

                    $res['data'][$key]['account'] = $user_account_info['account'];
                }
            } else {
                $res['data'][$key]['account'] = '';
            }

            if ($val['sign_num'] < 0) {
                $res['data'][$key]['sign_num'] = 0;
            }
        }
        return $res;
    }

    /**
     * 查询今日已签到的所有的apply_id
     * @param act_id
     */
    public function getActApplyId($act_id)
    {
        $activitySignObj = new ActivitySign();
        return $activitySignObj->where(function ($query) use ($act_id) {
            if ($act_id) {
                $act_id = is_string($act_id) ? explode(',', $act_id) : $act_id;
                $query->whereIn('act_id', $act_id);
            }
        })->where('date', date('Y-m-d'))->pluck('apply_id')->toArray();
    }

    /**
     * 获取我的活动个数
     * @param user_id
     */
    public function getMyActivityNumber($user_id)
    {
        $res = $this->where('user_id', $user_id)->groupBy('act_id')->pluck('id');
        return count($res);
    }



    /**
     * 获取未审核活动个数
     * @param  act_id 活动id  空表示全部
     */
    public function getUncheckedActivityNumber($act_id = null)
    {
        return $this->where(function ($query) use ($act_id) {
            if ($act_id) {
                $query->where('act_id', $act_id);
            }
        })->where('status', 4)->count();
    }


    /**
     * 审核通过 和 拒绝
     * @param id int 申请id
     * @param status int 状态  1.已通过 3.已拒绝
     */
    public function agreeAndRefused($id, $status, $reason = null)
    {
        $res = $this->where('id', $id)->first();
        if (!$res) {
            throw new Exception("参数传递错误");
        }

        if ($res->status != 4) {
            throw new Exception("不处于未审核状态");
        }

        $res->status = $status;
        if ($status == 3) {
            $res->reason = $reason;
        }
        $res->manage_id = request()->manage_id;
        $res->save();
        return $res;
    }




    /**
     * 活动类型统计(折线图)
     * @param $act_id 活动id
     * @param start_time 单位id 开始时间
     * @param end_time 单位id 结束时间
     * @param node  方式  1 年  2 月   3 日  如果为空，则根据实际来
     */
    public function applyStatistics($act_id = null, $start_time = null, $end_time = null, $node = null)
    {
        if ($node == 3 || (empty($node) && date('Y-m-d', strtotime($start_time)) == date('Y-m-d', strtotime($end_time)))) {
            $field = ['id', DB::raw("DATE_FORMAT(create_time,'%Y-%m-%d %H') as times"), DB::raw("count(id) as number")];
        } elseif ($node == 2 || (empty($node) && date('Y-m', strtotime($start_time)) == date('Y-m', strtotime($end_time)))) {
            $field = ['id', DB::raw("DATE_FORMAT(create_time,'%Y-%m-%d %H') as times"), DB::raw("count(id) as number")];
        } else {
            $field = ['id', DB::raw("DATE_FORMAT(create_time,'%Y-%m-%d') as times"), DB::raw("count(id) as number")];
        }
        $res = $this->select($field)->where(function ($query) use ($act_id, $start_time, $end_time) {
            if ($act_id) {
                $query->where('id', $act_id);
            }
            if ($start_time && $end_time) {
                $query->whereBetween('create_time', [$start_time, $end_time]);
            }
        })->orderBy('times')
            ->groupBy('times')
            ->get()
            ->toArray();

        return $res;
    }


    /**
     * 判断是否可以取消
     */
    public function isCanCancel($activity, $activity_apply)
    {
        if ($activity['is_apply'] == 2) {
            return "当前状态不能取消报名"; //不需要报名的活动，不需要去掉
        }

        if ($activity_apply && $activity_apply['status'] == 2) {
            return "当前状态不能取消报名"; //审核通过可以取消
        }
        if ($activity_apply && $activity['is_check'] == 1 && $activity_apply['status'] != 4) {
            return "当前状态不能取消报名"; //审核通过可以取消
        }
        if ($activity_apply && $activity['is_check'] == 2 && $activity_apply['status'] != 1) {
            return "当前状态不能取消报名"; //审核通过可以取消
        }

        if ($activity['start_time'] < date('Y-m-d H:i:s')) {
            return "活动即将开始，不允许取消";
        }
        //取消时间已报名结束为准
        if ($activity['cancel_end_time'] && (time() + $activity['cancel_end_time'] * 60 > strtotime($activity['apply_end_time']))) {
            return '已超过活动可取消时间';
        }

        return true;
    }


    /**
     * 判断是否可以显示二维码
     * @param $apply_info 报名信息
     * @param $apply_id 报名id
     * @param $user_id 用户id
     */
    public function isCanShowQr($user_id, $apply_id, $apply_info = null)
    {
        if (empty($apply_id) && empty($apply_info)) {
            return '报名信息不存在';
        }
        if (empty($apply_info)) {
            $apply_info = $this->where('id', $apply_id)->where('user_id', $user_id)->first();
        }

        if (empty($apply_info)) {
            return '报名信息不存在';
        }
        if ($apply_info->status != 1) {
            return '当前状态不能出示二维码';
        }

        // 活动是否存在
        $act_info = Activity::select('id', 'title', 'is_apply', 'is_long', 'start_time', 'end_time', 'everyday_start_time', 'everyday_end_time', 'sign_way')
            ->where("id", $apply_info->act_id)
            ->where("is_del", 1)
            ->where("is_play", 1)
            ->first();

        if (empty($act_info)) return "活动不存在或已被删除";
        if ($act_info['end_time'] < date("Y-m-d", strtotime("-1 days"))) return '活动已经结束很久了,不能出示二维码';
        if ($act_info['sign_way'] == 2) return '请使用扫码功能进行扫码操作';


        /**检查签到时间 */
        $date = time();
        //长期活动，在每日的开始前30分钟 ~ 结束的前30分钟为签到时间；短期活动，在活动的开始前30分钟 ~ 结束的前30分钟为签到时间；
        if ($act_info['is_long'] == 1) {
            if ($date < strtotime(date("Y-m-d") . ' ' . $act_info['everyday_start_time']) - 30 * 60 || $date >= strtotime(date("Y-m-d") . ' ' . $act_info['everyday_end_time']) - 30 * 60) {
                return '当前时间不在打卡范围内';
            }
        } else {
            if ($date < strtotime($act_info['start_time']) - 30 * 60 || $date >= strtotime($act_info['end_time']) - 30 * 60) {
                return '当前时间不在打卡范围内';
            }
        }
        return true;
    }

    /**
     * 将逾期未签到的数据，进行积分处理
     */
    public function checkApplyStatus()
    {
        $res = $this->from($this->getTable() . ' as p')
            ->join('activity as a', 'p.act_id', '=', 'a.id')
            ->select('p.id', 'p.user_id', 'p.account_id', 'p.act_id', 'a.end_time', 'p.sign_num', 'a.is_reader')
            ->where('status', 1)
            ->where('a.end_time', '<', date('Y-m-d H:i:s'))
            ->where('a.is_reader', 1)
            ->where('a.is_del', 1)
            ->where('a.is_long', 2) //只处理短期活动
            ->where('sign_num', 0) //未签过到
            ->get()->toArray();
        foreach ($res as $key => $val) {
            //操作积分
            $scoreRuleObj = new ScoreRuleController();
            $score_status = $scoreRuleObj->checkScoreStatus(22, $val["user_id"], $val["account_id"]);
            // 这里 203 也要操作
            if ($score_status['code'] == 202) {
                Log::error('活动逾期未签到,积分处理失败，报名ID:' . $val['id']);
                Log::error($score_status['msg']);
                continue;
            }
            if ($score_status['code'] == 200 || ($score_status['code'] == 203 && !empty($score_status['user_score']))) {
                $scoreRuleObj->scoreChange($score_status, $val["user_id"], $val["account_id"], $val['id']); //添加积分消息
            }
            $this->where('id', $val['id'])->update(['sign_num' => -1, 'change_time' => $val['end_time']]); //修改为与缺席
        }
    }

    /**
     * 获取用户参数活动次数
     * @param user_id 用户id
     */
    public function getUserApplyNumber($user_id)
    {
        return $this->where('user_id', $user_id)->whereIn('status', [1, 4])->count();
    }


    /**
     * 活动类型统计数据
     * @param $user_id 用户id
     * @param start_time 单位id 开始时间
     * @param end_time 单位id 结束时间
     */
    public function userApplyTypeStatistics($user_id = null)
    {
        $res = $this->from($this->getTable() . ' as p')
            ->join('activity as a', 'a.id', '=', 'p.act_id')
            ->join('activity_type as t', 't.id', '=', 'a.type_id')
            ->select("type_id", 't.type_name', DB::raw("count(type_id) as count"))->where(function ($query) use ($user_id) {
                if ($user_id) {
                    $query->where('p.user_id', $user_id);
                }
            })->orderByDesc('count')
            ->groupBy('type_id')
            ->get()
            ->toArray();
        return $res;
    }

    /**
     * 获取报名头像和昵称
     * @param act_id 活动id
     */
    public function getApplyActivityUserInfo($act_id, $field = ['nickname', 'head_img'], $limit = 6)
    {
        return $this->select($field)->from($this->getTable() . ' as a')
            ->join('user_info as u', 'u.id', '=', 'a.user_id')
            ->where('act_id', $act_id)
            ->whereIn('a.status', [1, 4])
            ->groupBy('user_id')
            ->orderByDesc('a.id')
            ->limit($limit)
            ->get()
            ->toArray();
    }
}
